﻿using System;
using System.ComponentModel;
using System.Windows;
using System.Windows.Controls;
using System.Windows.Documents;
using System.Windows.Input;
using System.Windows.Media;
using System.Windows.Media.Imaging;
using System.Windows.Shapes;
using System.Xml;
using SHomeWorkshop.LunarPresentation.Adorners;
using SHomeWorkshop.LunarPresentation.Expressions;
using SHomeWorkshop.LunarPresentation.Widegets;

namespace SHomeWorkshop.LunarPresentation
{
    public class Editor : TabItem, INotifyPropertyChanged
    {
        /// <summary>
        /// 新建一个编辑器。
        /// </summary>
        /// <param name="parentWindow">传入程序主窗口。</param>
        /// <param name="xmlDocument">如果此参数为默认值（null）则会自动新建一个。</param>
        public Editor(MainWindow parentWindow, XmlDocument xmlDocument = null)
        {
            this.ParentWindow = parentWindow;
            this.SnapsToDevicePixels = true;

            this.baseScrolledViewer = new ScrollViewer()
            {
                //IsDeferredScrollingEnabled = true,
                VerticalScrollBarVisibility = ScrollBarVisibility.Auto,
                HorizontalScrollBarVisibility = ScrollBarVisibility.Auto
            };

            this.baseScrolledViewer.PreviewKeyDown
                += new System.Windows.Input.KeyEventHandler(baseScrolledViewer_PreviewKeyDown);

            //鼠标滚轮事件
            this.baseScrolledViewer.PreviewMouseWheel
                += new System.Windows.Input.MouseWheelEventHandler(baseScrolledViewer_PreviewMouseWheel);

            this.baseScrolledViewer.Background = defaultBackground;

            this.baseScrolledViewer.SizeChanged += new SizeChangedEventHandler(baseScrolledViewer_SizeChanged);

            //鼠标右键卷动
            //鼠标移动事件
            this.baseScrolledViewer.PreviewMouseRightButtonDown +=
                new MouseButtonEventHandler(baseScrolledViewer_PreviewMouseRightButtonDown);
            this.baseScrolledViewer.PreviewMouseRightButtonUp +=
                new MouseButtonEventHandler(baseScrolledViewer_PreviewMouseRightButtonUp);
            this.baseScrolledViewer.PreviewMouseMove +=
                new MouseEventHandler(baseScrolledViewer_PreviewMouseMove);

            #region 初始化选项卡头的文件名和只读标记、文档被修改标记、关闭选项卡（表示关闭文档）按钮。
            StackPanel panel = new StackPanel();

            panel.Orientation = Orientation.Horizontal;

            #region 只读文档标记。
            readonlyCanvas = new Canvas()
            {
                VerticalAlignment = VerticalAlignment.Center,
                Height = 10,
                Width = 10,
            };

            readonlyCanvas.Visibility = Visibility.Collapsed;
            readonlyCanvas.Margin = new Thickness(0, 0, 4, 0);
            RenderOptions.SetEdgeMode(readonlyCanvas, EdgeMode.Aliased);

            Rectangle rt1 = new Rectangle()
            {
                Width = 8,
                Height = 4,
                Fill = Brushes.Brown,
            };
            readonlyCanvas.Children.Add(rt1);
            Canvas.SetLeft(rt1, 1); Canvas.SetTop(rt1, 5);

            Rectangle rt2 = new Rectangle()
            {
                Width = 4,
                Height = 6,
                Stroke = Brushes.Brown,
                Fill = Brushes.Transparent,
            };
            readonlyCanvas.Children.Add(rt2);
            Canvas.SetLeft(rt2, 3); Canvas.SetTop(rt2, 2);

            #endregion

            #region 文档被修改标记。
            textBlockModified = new TextBlock();
            textBlockModified.SetValue(TextOptions.TextFormattingModeProperty, TextFormattingMode.Display);
            textBlockModified.Visibility = Visibility.Collapsed;
            textBlockModified.Text = "*";
            #endregion

            imgClose = new Image() { VerticalAlignment = VerticalAlignment.Center };
            imgClose.VerticalAlignment = VerticalAlignment.Center;
            imgClose.ToolTip = "关闭";

            activeImg = new BitmapImage(new Uri("pack://application:,,,/LunarPresentation;component/Resources/Icons/CloseHS2.png"));
            normalImg = new BitmapImage(new Uri("pack://application:,,,/LunarPresentation;component/Resources/Icons/CloseHS.png"));
            imgClose.Source = normalImg;
            imgClose.Height = 16;
            imgClose.MouseLeftButtonDown += new System.Windows.Input.MouseButtonEventHandler(imgClose_MouseLeftButtonDown);

            imgClose.Margin = new Thickness(4, 0, 0, 0);
            imgClose.MouseEnter += new System.Windows.Input.MouseEventHandler(imgClose_MouseEnter);
            imgClose.MouseLeave += new System.Windows.Input.MouseEventHandler(imgClose_MouseLeave);

            fileNameHeader = new TextBlock();
            fileNameHeader.SetValue(TextOptions.TextFormattingModeProperty, TextFormattingMode.Display);
            fileNameHeader.Text = "新文档";

            panel.VerticalAlignment = VerticalAlignment.Center;

            panel.Children.Add(readonlyCanvas);
            panel.Children.Add(textBlockModified);
            panel.Children.Add(fileNameHeader);
            panel.Children.Add(imgClose);

            this.Header = panel;
            #endregion

            this.EditorBeforeClosed += new EventHandler<EditorBeforeClosedEventArgs>(EditorOfExpression_EditorBeforeClosed);

            this.rootPanel = new SubPanel(null, null, this, null);

            // 根面板与所有其它面板均不同，其尺寸不完全由自身决定。
            // 这是为了让出文本块编辑器要占据的位置。
            this.rootPanel.Margin = new Thickness(2, 2, 2, 166);
            //this.rootPanel.BasePanel.Margin = new Thickness(0, 0, 0, 100);
            this.rootPanel.VerticalAlignment = VerticalAlignment.Stretch;
            this.rootPanel.HorizontalAlignment = HorizontalAlignment.Stretch;

            this.baseScrolledViewer.Focusable = false;
            //这句不能少，缺这句导致选中某个公式时，Alt+“X”弹不出菜单。

            this.mainDecorator = new AdornerDecorator();
            mainBorder = new Border();
            mainBorder.Background = Editor.backgroundImage;
            mainBorder.Child = this.baseScrolledViewer;
            mainBorder.BorderBrush = Brushes.LightBlue;
            mainBorder.BorderThickness = new Thickness(1);

            this.mainDecorator.Child = mainBorder;

            #region 编辑器选项卡头
            DockPanel dPanelBase = new DockPanel() { LastChildFill = true };
            this.dPanelPageHeader = new DockPanel()
            {
                Background = Brushes.LightGray,
                Margin = new Thickness(20, 4, 20, 4),
                LastChildFill = true,
                Visibility = Visibility.Collapsed,
                HorizontalAlignment = HorizontalAlignment.Stretch
            };

            this.tbPageHeaderLeft = new TextBlock()
            {
                Foreground = Brushes.Blue,
                TextAlignment = TextAlignment.Left,
                TextWrapping = TextWrapping.Wrap
            };

            this.tbPageHeaderRight = new TextBlock()
            {
                Foreground = Brushes.Blue,
                TextAlignment = TextAlignment.Right,
                TextWrapping = TextWrapping.Wrap
            };

            this.tbPageHeaderMiddle = new TextBlock()
            {
                Foreground = Brushes.Blue,
                TextAlignment = TextAlignment.Center,
                TextWrapping = TextWrapping.Wrap
            };

            this.tbPageHeaderLeft.MouseLeftButtonDown += new MouseButtonEventHandler(tbPageHeader_MouseLeftButtonDown);
            this.tbPageHeaderMiddle.MouseLeftButtonDown += new MouseButtonEventHandler(tbPageHeader_MouseLeftButtonDown);
            this.tbPageHeaderRight.MouseLeftButtonDown += new MouseButtonEventHandler(tbPageHeader_MouseLeftButtonDown);

            this.dPanelPageHeader.Children.Add(this.tbPageHeaderLeft);
            this.dPanelPageHeader.Children.Add(this.tbPageHeaderRight);//注意顺序
            this.dPanelPageHeader.Children.Add(this.tbPageHeaderMiddle);//最后添加中间一个

            DockPanel.SetDock(this.tbPageHeaderLeft, Dock.Left);
            DockPanel.SetDock(this.tbPageHeaderRight, Dock.Right);

            DockPanel.SetDock(this.dPanelPageHeader, Dock.Top);

            dPanelBase.Children.Add(this.dPanelPageHeader);
            dPanelBase.Children.Add(this.mainDecorator);
            #endregion

            //this.Content = this.mainDecorator;
            this.Content = dPanelBase;

            // 这个装饰层只是备用。
            //AdornerLayer adornerLayer = AdornerLayer.GetAdornerLayer(this.baseScrolledViewer);
            //mainAdorner = new DragingAdorner(this.baseScrolledViewer) { Visibility = Visibility.Hidden };
            //adornerLayer.Add(mainAdorner);

            this.paperSizeLineDecorator = new AdornerDecorator();
            this.paperSizeLineAdorner = new PaperSizeLineAdorner(this, this.rootPanel);
            this.paperSizeLineDecorator.AdornerLayer.Add(this.paperSizeLineAdorner);

            //根面板外套一个装饰层，用以显示标尺线。
            //本程序不支持直接打印，但支持图片导出后打印，这个标尺线就是用在估算当前文档导出为图片时的尺寸。

            this.paperSizeLineDecorator.Child = this.rootPanel;
            this.baseScrolledViewer.Content = this.paperSizeLineDecorator;

            #region 初始化一个Xml文档。
            if (xmlDocument != null)
            {
                this.XmlDocument = xmlDocument;
                this.rootPanel.XmlData = this.xmlDocument.DocumentElement;
            }
            else
            {
                XmlDocument newDocument = new XmlDocument();
                newDocument.InnerXml = LunarPresentation.Properties
                    .Resources.InitDocument;

                this.XmlDocument = newDocument;
            }
            #endregion

            this.SelectionExpressionChanging +=
                new EventHandler<SelectionExpressionChangingEventArgs>(EditorOfExpression_SelectionExpressionChanging);
            this.SelectionExpressionChanged +=
                new EventHandler<SelectionExpressionChangedEventArgs>(EditorOfExpression_SelectionExpressionChanged);

            //UndoList 初始化
            modifingsList = new ModifingsList(this);

            //初始化几个“默认属性”。

            if (xmlDocument == null || xmlDocument.DocumentElement == null)//如果没有传入文档。
            {
                this.DefaultBackground = Editor.NewDocDefaultBackground;

                this.DefaultForeground = Editor.NewDocDefaultForeground;
                this.ExSelectionAdornerBrush = Editor.NewDocDefaultSelectBox1Brush;
                this.SubPanelSelectionAdornerBrush = Editor.NewDocDefaultSelectBox2Brush;

                this.DefHeaderText1Brush = Editor.NewDocDefaultHeaderText1Brush;
                this.DefHeaderText2Brush = Editor.NewDocDefaultHeaderText2Brush;
                this.DefHeaderText3Brush = Editor.NewDocDefaultHeaderText3Brush;
                this.DefHeaderText4Brush = Editor.NewDocDefaultHeaderText4Brush;
            }
            else //if(xmlDocument != null)
            {
                XmlAttribute attrDefBackground = xmlDocument.DocumentElement.GetAttributeByName("DefaultBackground");
                if (attrDefBackground == null || attrDefBackground.Value.Length <= 0)
                {
                    this.DefaultBackground = Editor.NewDocDefaultBackground;
                }

                XmlAttribute attrDefForeground = xmlDocument.DocumentElement.GetAttributeByName("DefaultForeground");
                if (attrDefForeground == null || attrDefForeground.Value.Length <= 0)
                {
                    this.DefaultForeground = Editor.NewDocDefaultForeground;
                }

                XmlAttribute attrExSelectionAdornerBrush = xmlDocument.DocumentElement.GetAttributeByName("ExSelectionAdornerBrush");
                if (attrExSelectionAdornerBrush == null || attrExSelectionAdornerBrush.Value.Length <= 0)
                {
                    this.ExSelectionAdornerBrush = Editor.NewDocDefaultSelectBox1Brush;
                }

                XmlAttribute attrSubPanelSelectionAdornerBrush = xmlDocument.DocumentElement.GetAttributeByName("SubPanelSelectionAdornerBrush");
                if (attrSubPanelSelectionAdornerBrush == null || attrSubPanelSelectionAdornerBrush.Value.Length <= 0)
                {
                    this.SubPanelSelectionAdornerBrush = Editor.NewDocDefaultSelectBox2Brush;
                }

                XmlAttribute attrDefaultHeaderText1Color = xmlDocument.DocumentElement.GetAttributeByName("DefaultHeaderText1Color");
                if (attrDefaultHeaderText1Color == null || attrDefaultHeaderText1Color.Value.Length <= 0)
                {
                    this.DefHeaderText1Brush = Editor.NewDocDefaultHeaderText1Brush;
                }

                XmlAttribute attrDefaultHeaderText2Color = xmlDocument.DocumentElement.GetAttributeByName("DefaultHeaderText2Color");
                if (attrDefaultHeaderText2Color == null || attrDefaultHeaderText2Color.Value.Length <= 0)
                {
                    this.DefHeaderText2Brush = Editor.NewDocDefaultHeaderText2Brush;
                }

                XmlAttribute attrDefaultHeaderText3Color = xmlDocument.DocumentElement.GetAttributeByName("DefaultHeaderText3Color");
                if (attrDefaultHeaderText3Color == null || attrDefaultHeaderText3Color.Value.Length <= 0)
                {
                    this.DefHeaderText3Brush = Editor.NewDocDefaultHeaderText3Brush;
                }

                XmlAttribute attrDefaultHeaderText4Color = xmlDocument.DocumentElement.GetAttributeByName("DefaultHeaderText4Color");
                if (attrDefaultHeaderText4Color == null || attrDefaultHeaderText4Color.Value.Length <= 0)
                {
                    this.DefHeaderText4Brush = Editor.NewDocDefaultHeaderText4Brush;
                }
            }

            if (this.IsModified)
            {
                this.IsModified = false;
            }
        }

        private PageSettings pageSettingInfo = new PageSettings();

        public PageSettings PageSettingInfo
        {
            get { return pageSettingInfo; }
        }

        public string PageSettingInfoSource
        {
            set
            {
                pageSettingInfo.SetPageSettings(value);
                paperSizeLineAdorner.PaperName = pageSettingInfo.PaperName;
                paperSizeLineAdorner.PageMargin = new Thickness(
                    pageSettingInfo.MarginLeft,
                    pageSettingInfo.MarginTop,
                    pageSettingInfo.MarginRight,
                    pageSettingInfo.MarginBottom
                    );

                this.xmlDocument.DocumentElement.SetAttribute("PageSettingInfo", value);
            }
        }

        void tbPageHeader_MouseLeftButtonDown(object sender, MouseButtonEventArgs e)
        {
            Commands.Command.RunTextCmd("ym");
        }

        private AdornerDecorator paperSizeLineDecorator;

        /// <summary>
        /// 纸张标尺线装饰层。
        /// </summary>
        public AdornerDecorator PaperSizeLineDecorator
        {
            get { return paperSizeLineDecorator; }
        }

        private PaperSizeLineAdorner paperSizeLineAdorner;

        /// <summary>
        /// 纸张标尺线装饰器。
        /// </summary>
        public PaperSizeLineAdorner PaperSizeLineAdorner
        {
            get { return paperSizeLineAdorner; }
            set { paperSizeLineAdorner = value; }
        }

        private string maxWidthOfRootPanel = "max";

        /// <summary>
        /// 整个根面板的最大宽度。默认为double.MaxValue。
        /// </summary>
        public string MaxWidthOfRootPanel
        {
            get { return maxWidthOfRootPanel; }
            set
            {
                maxWidthOfRootPanel = value;

                if (maxWidthOfRootPanel.ToLower() == "max")
                {
                    this.RootPanel.MaxWidth = double.MaxValue;
                }
                else
                {
                    PaperInfo pi = PaperInfo.GetPaperInfo(maxWidthOfRootPanel);

                    if (pi == null) return;

                    this.RootPanel.MaxWidth = pi.ShortSideWPFUnit;
                }

                this.xmlDocument.DocumentElement.SetAttribute("MaxWidthOfRootPanel", maxWidthOfRootPanel.ToString());
                OnPropertyChanged(this, new PropertyChangedEventArgs("MaxWidthOfRootPanel"));
            }
        }

        private double maxTextWidth = 600;

        public double MaxTextWidth
        {
            get { return maxTextWidth; }
            set
            {
                maxTextWidth = value;
                this.xmlDocument.DocumentElement.SetAttribute("MaxTextWidth", maxTextWidth.ToString());
                OnPropertyChanged(this, new PropertyChangedEventArgs("MaxTextWidth"));
            }
        }

        void baseScrolledViewer_SizeChanged(object sender, SizeChangedEventArgs e)
        {
            //用以在窗口最大化、恢复操作后，刷新标题文本块的树型线。
            //经实践证明：此方法用在主窗口的SizeChanged事件中无效。
            Expressions.SubPanel.RefreshHeaderTextTreeLines(RootPanel);
        }

        private DockPanel dPanelPageHeader;

        private TextBlock tbPageHeaderLeft;

        private TextBlock tbPageHeaderRight;

        private TextBlock tbPageHeaderMiddle;

        private void RefreshPageHeader()
        {
            if ((this.tbPageHeaderLeft.Text == null || this.tbPageHeaderLeft.Text == "") &&
                (this.tbPageHeaderRight.Text == null || this.tbPageHeaderRight.Text == "") &&
                (this.tbPageHeaderMiddle.Text == null || this.tbPageHeaderMiddle.Text == ""))
            {
                this.dPanelPageHeader.Visibility = Visibility.Collapsed;
            }
            else
            {
                this.dPanelPageHeader.Visibility = Visibility.Visible;
            }
        }

        public void RefreshPageHeaderLeft(string newTextHeader)
        {
            if (newTextHeader != null)
            {
                this.tbPageHeaderLeft.Text = newTextHeader;
            }
            else
            {
                this.tbPageHeaderLeft.Text = "";
            }

            RefreshPageHeader();
        }

        public void RefreshPageHeaderRight(string newTextHeader)
        {
            if (newTextHeader != null)
            {
                this.tbPageHeaderRight.Text = newTextHeader;
            }
            else
            {
                this.tbPageHeaderRight.Text = "";
            }

            RefreshPageHeader();
        }

        public void RefreshPageHeaderMiddle(string newTextHeader)
        {
            if (newTextHeader != null)
            {
                this.tbPageHeaderMiddle.Text = newTextHeader;
            }
            else
            {
                this.tbPageHeaderMiddle.Text = "";
            }

            RefreshPageHeader();
        }

        public string PageHeaderLeft
        {
            get { return tbPageHeaderLeft.Text; }
            set
            {
                this.RefreshPageHeaderLeft(value);
                this.xmlDocument.DocumentElement.SetAttribute("PageHeaderLeft", value);
            }
        }

        public string PageHeaderMiddle
        {
            get { return tbPageHeaderMiddle.Text; }
            set
            {
                this.RefreshPageHeaderMiddle(value);
                this.xmlDocument.DocumentElement.SetAttribute("PageHeaderMiddle", value);
            }
        }

        public string PageHeaderRight
        {
            get { return tbPageHeaderRight.Text; }
            set
            {
                this.RefreshPageHeaderRight(value);
                this.xmlDocument.DocumentElement.SetAttribute("PageHeaderRight", value);
            }
        }

        /// <summary>
        /// 编辑器背景图。
        /// </summary>
        private static ImageBrush backgroundImage = null;

        static Editor()
        {
            //<ImageBrush Stretch="UniformToFill" TileMode="FlipXY" ViewportUnits="Absolute" Viewport="64,64,64,64"
            //                ImageSource="pack://application:,,,/WpfExpressions;component/Resources/backImg.jpg"/>
            backgroundImage = new ImageBrush();
            backgroundImage.ImageSource = new BitmapImage(
                new Uri("pack://Application:,,,/LunarPresentation;component/Resources/EditorBackground.jpg"));
            backgroundImage.TileMode = TileMode.FlipXY;
            backgroundImage.ViewportUnits = BrushMappingMode.Absolute;
            backgroundImage.Viewport = new Rect(64, 64, 64, 64);
            backgroundImage.Stretch = Stretch.UniformToFill;

            //载入一些新建文档时的默认属性值。
            if (System.IO.File.Exists(Globals.pathOfPreferences))
            {
                try
                {
                    XmlDocument xDoc = XmlTools.LoadXmlFile(Globals.pathOfPreferences);
                    if (xDoc == null) return;

                    XmlNode root = xDoc.SelectSingleNode("/Root");
                    XmlNode newDocDefSettiongs = root.SelectSingleNode("NewDocDefSettings");
                    if (newDocDefSettiongs == null) return;

                    XmlNode newDocDefBackNode = newDocDefSettiongs.SelectSingleNode("DefBackground");
                    XmlNode newDocDefForeNode = newDocDefSettiongs.SelectSingleNode("DefForeground");
                    XmlNode newDocDefSelBox1Node = newDocDefSettiongs.SelectSingleNode("DefSelBox1Color");
                    XmlNode newDocDefSelBox2Node = newDocDefSettiongs.SelectSingleNode("DefSelBox2Color");

                    XmlNode newDocDefHeaderText1Node = newDocDefSettiongs.SelectSingleNode("DefHeaderText1Color");
                    XmlNode newDocDefHeaderText2Node = newDocDefSettiongs.SelectSingleNode("DefHeaderText2Color");
                    XmlNode newDocDefHeaderText3Node = newDocDefSettiongs.SelectSingleNode("DefHeaderText3Color");
                    XmlNode newDocDefHeaderText4Node = newDocDefSettiongs.SelectSingleNode("DefHeaderText4Color");

                    if (newDocDefBackNode != null && newDocDefForeNode != null &&
                        newDocDefSelBox1Node != null && newDocDefSelBox2Node != null)
                    {
                        Brush bsh1, bsh2, bsh3, bsh4;

                        bsh1 = ColorPicker.GetBrushByName(newDocDefBackNode.InnerText);
                        bsh2 = ColorPicker.GetBrushByName(newDocDefForeNode.InnerText);
                        bsh3 = ColorPicker.GetBrushByName(newDocDefSelBox1Node.InnerText);
                        bsh4 = ColorPicker.GetBrushByName(newDocDefSelBox2Node.InnerText);
                        if (bsh1 != null && bsh2 != null && bsh3 != null && bsh4 != null)
                        {
                            Editor.NewDocDefaultBackground = bsh1;
                            Editor.NewDocDefaultForeground = bsh2;
                            Editor.NewDocDefaultSelectBox1Brush = bsh3;
                            Editor.NewDocDefaultSelectBox2Brush = bsh4;
                        }
                    }

                    if (newDocDefHeaderText1Node != null && newDocDefHeaderText2Node != null &&
                        newDocDefHeaderText3Node != null && newDocDefHeaderText4Node != null)
                    {
                        Brush bsh1, bsh2, bsh3, bsh4;

                        bsh1 = ColorPicker.GetBrushByName(newDocDefHeaderText1Node.InnerText);
                        bsh2 = ColorPicker.GetBrushByName(newDocDefHeaderText2Node.InnerText);
                        bsh3 = ColorPicker.GetBrushByName(newDocDefHeaderText3Node.InnerText);
                        bsh4 = ColorPicker.GetBrushByName(newDocDefHeaderText4Node.InnerText);
                        if (bsh1 != null && bsh2 != null && bsh3 != null && bsh4 != null)
                        {
                            Editor.NewDocDefaultHeaderText1Brush = bsh1;
                            Editor.NewDocDefaultHeaderText2Brush = bsh2;
                            Editor.NewDocDefaultHeaderText3Brush = bsh3;
                            Editor.NewDocDefaultHeaderText4Brush = bsh4;
                        }
                    }
                    else
                    {
                        Editor.NewDocDefaultHeaderText1Brush = Editor.NewDocDefaultForeground;
                        Editor.NewDocDefaultHeaderText2Brush = Editor.NewDocDefaultForeground;
                        Editor.NewDocDefaultHeaderText3Brush = Editor.NewDocDefaultForeground;
                        Editor.NewDocDefaultHeaderText4Brush = Editor.NewDocDefaultForeground;
                    }
                }
                catch (Exception ex)
                {
                    Dialogs.LunarMsgBox.MsgBoxShow(
                        Globals.appName,
                        "读取“Preferences.xml”文件发生意外，未能载入偏好设置。",
                        "异常信息如下：\r\n" + ex.Message,
                        ex.StackTrace, MessageBoxButton.OK, MessageBoxImage.Warning);
                    return;
                }
            }
        }

        private static Brush newDocDefaultBackground = Brushes.Black;

        /// <summary>
        /// 新建一个文档时，缺省情况应将此文档的“默认背景色”设置为此色。
        /// </summary>
        public static Brush NewDocDefaultBackground
        {
            get { return Editor.newDocDefaultBackground; }
            set { Editor.newDocDefaultBackground = value; }
        }

        private static Brush newDocDefaultForeground = Brushes.White;

        /// <summary>
        /// 新建一个文档时，缺省情况应将此文档的“默认前景色”设置为此色。
        /// </summary>
        public static Brush NewDocDefaultForeground
        {
            get { return Editor.newDocDefaultForeground; }
            set { Editor.newDocDefaultForeground = value; }
        }

        private static Brush newDocDefaultSelectBox1Brush = Brushes.GreenYellow;

        /// <summary>
        /// 新建一个文档时，缺省情况应将此文档的“默认选择框色１”设置为此色。
        /// </summary>
        public static Brush NewDocDefaultSelectBox1Brush
        {
            get { return Editor.newDocDefaultSelectBox1Brush; }
            set { Editor.newDocDefaultSelectBox1Brush = value; }
        }

        private static Brush newDocDefaultSelectBox2Brush = Brushes.HotPink;

        /// <summary>
        /// 新建一个文档时，缺省情况应将此文档的“默认选择框色２”设置为此色。
        /// </summary>
        public static Brush NewDocDefaultSelectBox2Brush
        {
            get { return Editor.newDocDefaultSelectBox2Brush; }
            set { Editor.newDocDefaultSelectBox2Brush = value; }
        }

        private static Brush newDocDefaultHeaderText1Brush = Brushes.White;

        /// <summary>
        /// 新建一个文档时，缺省情况应将此文档的“默认１级标题文本色彩”设置为此色。
        /// </summary>
        public static Brush NewDocDefaultHeaderText1Brush
        {
            get { return Editor.newDocDefaultHeaderText1Brush; }
            set { Editor.newDocDefaultHeaderText1Brush = value; }
        }

        private static Brush newDocDefaultHeaderText2Brush = Brushes.White;

        /// <summary>
        /// 新建一个文档时，缺省情况应将此文档的“默认２级标题文本色彩”设置为此色。
        /// </summary>
        public static Brush NewDocDefaultHeaderText2Brush
        {
            get { return Editor.newDocDefaultHeaderText2Brush; }
            set { Editor.newDocDefaultHeaderText2Brush = value; }
        }

        private static Brush newDocDefaultHeaderText3Brush = Brushes.White;

        /// <summary>
        /// 新建一个文档时，缺省情况应将此文档的“默认３级标题文本色彩”设置为此色。
        /// </summary>
        public static Brush NewDocDefaultHeaderText3Brush
        {
            get { return Editor.newDocDefaultHeaderText3Brush; }
            set { Editor.newDocDefaultHeaderText3Brush = value; }
        }

        private static Brush newDocDefaultHeaderText4Brush = Brushes.White;

        /// <summary>
        /// 新建一个文档时，缺省情况应将此文档的“默认４级标题文本色彩”设置为此色。
        /// </summary>
        public static Brush NewDocDefaultHeaderText4Brush
        {
            get { return Editor.newDocDefaultHeaderText4Brush; }
            set { Editor.newDocDefaultHeaderText4Brush = value; }
        }

        private Border mainBorder;

        private Brush defaultForeground = Brushes.White;

        public Brush DefaultForeground
        {
            get { return defaultForeground; }
            set
            {
                defaultForeground = value;
                RefreshAllExForeground(rootPanel);
                rootPanel.XmlData.SetAttribute("DefaultForeground", ColorPicker.GetBrushName(value));
            }
        }

        private void RefreshAllExForeground(Expressions.Expression ex)
        {
            if (ex == null) return;

            System.Xml.XmlAttribute attrExForeground = ex.XmlData.GetAttribute("ExForeground");
            if (attrExForeground == null)
            {
                Expressions.BaseText bt = ex as Expressions.BaseText;
                if (bt == null || bt.IsHeaderText == false)
                {
                    ex.UpdateExForegroundWithoutXmlChanging(defaultForeground);
                }
                else
                {
                    bt.RefreshExForeground();
                }
            }

            if (ex is SubPanel)
            {
                SubPanel spanel = ex as SubPanel;
                foreach (UIElement ue in spanel.BasePanel.Children)
                {
                    Expressions.Expression subEx = ue as Expressions.Expression;

                    if (subEx != null)
                    {
                        RefreshAllExForeground(subEx);
                    }
                }

                if (spanel is GridPanel)
                {
                    //如果网格子面板未设置自己的边框色，则默认情况下与编辑器前景色一致。
                    //因为找不到取消绑定的方法。因此此处用递归实现更新。
                    XmlAttribute attrBorderColor = spanel.XmlData.GetAttribute("BorderColor");
                    if (attrBorderColor == null && spanel.Editor != null)
                    {
                        spanel.MainBorder.BorderBrush = spanel.Editor.DefaultForeground;
                    }
                }
            }
            else
            {
                if (ex is Expressions.Grid || ex is Expressions.Row)
                {
                    //如果网格子面板未设置自己的边框色，则默认情况下与编辑器前景色一致。
                    //因为找不到取消绑定的方法。因此此处用递归实现更新。
                    if (ex.XmlData != null)
                    {
                        XmlAttribute attrBorderColor = ex.XmlData.GetAttribute("BorderColor");
                        if (attrBorderColor == null && ex.Editor != null)
                        {
                            ex.MainBorder.BorderBrush = ex.Editor.DefaultForeground;
                        }
                    }
                }

                if (ex.SubPanels == null) return;

                foreach (SubPanel subPanel in ex.SubPanels)
                {
                    RefreshAllExForeground(subPanel);
                }
            }
        }

        public void RefreshDefaultBackgroundWithoutXml(Brush newBrush)
        {
            defaultBackground = newBrush;
            if (baseScrolledViewer != null)
            {
                baseScrolledViewer.Background = newBrush;
            }
        }

        private Brush defaultBackground = Brushes.Black;

        public Brush DefaultBackground
        {
            get { return defaultBackground; }
            set
            {
                defaultBackground = value;
                this.baseScrolledViewer.Background = value;
                rootPanel.XmlData.SetAttribute("DefaultBackground", ColorPicker.GetBrushName(value));
                OnPropertyChanged(this, new PropertyChangedEventArgs("DefaultBackground"));
            }
        }

        public string DefaultBackgroundXmlString
        {
            get
            {
                XmlAttribute attrDefBackground = this.xmlDocument.DocumentElement.GetAttributeByName("DefaultBackground");
                if (attrDefBackground != null)
                {
                    return attrDefBackground.Value;
                }
                else return null;
            }
        }

        private Brush defHeaderText1Brush = Brushes.White;

        public Brush DefHeaderText1Brush
        {
            get { return defHeaderText1Brush; }
            set
            {
                defHeaderText1Brush = value;
                RefreshAllExForeground(rootPanel);
                rootPanel.XmlData.SetAttribute("DefaultHeaderText1Color", ColorPicker.GetBrushName(value));
            }
        }

        private Brush defHeaderText2Brush = Brushes.White;

        public Brush DefHeaderText2Brush
        {
            get { return defHeaderText2Brush; }
            set
            {
                defHeaderText2Brush = value;
                RefreshAllExForeground(rootPanel);
                rootPanel.XmlData.SetAttribute("DefaultHeaderText2Color", ColorPicker.GetBrushName(value));
            }
        }

        private Brush defHeaderText3Brush = Brushes.White;

        public Brush DefHeaderText3Brush
        {
            get { return defHeaderText3Brush; }
            set
            {
                defHeaderText3Brush = value;
                RefreshAllExForeground(rootPanel);
                rootPanel.XmlData.SetAttribute("DefaultHeaderText3Color", ColorPicker.GetBrushName(value));
            }
        }

        private Brush defHeaderText4Brush = Brushes.White;

        public Brush DefHeaderText4Brush
        {
            get { return defHeaderText4Brush; }
            set
            {
                defHeaderText4Brush = value;
                RefreshAllExForeground(rootPanel);
                rootPanel.XmlData.SetAttribute("DefaultHeaderText4Color", ColorPicker.GetBrushName(value));
            }
        }


        /// <summary>
        /// 用于决定鼠标右键拖动时卷动的起点。
        /// </summary>
        private Point scrollStart = new Point(0, 0);

        private Point scrollStartOffcet = new Point(0, 0);

        private bool isScrolling = false;

        /// <summary>
        /// Expander、图片框都要用到鼠标右键，此时应禁用拖动事件。
        /// </summary>
        public bool IsScrolling
        {
            get { return isScrolling; }
            set { isScrolling = value; }
        }

        void baseScrolledViewer_PreviewMouseRightButtonUp(object sender, MouseButtonEventArgs e)
        {
            Point endPoint = e.GetPosition(baseScrolledViewer);

            //改由鼠标指针位置来决定是否显示右键菜单。
            if (Math.Abs(endPoint.X - scrollStart.X) < 4 && Math.Abs(endPoint.Y - scrollStart.Y) < 4)
            {
                SHomeWorkshop.LunarPresentation.ExContextMenus.OpenMenu(this);
            }

            isScrolling = false;
        }

        void baseScrolledViewer_PreviewMouseRightButtonDown(object sender, MouseButtonEventArgs e)
        {
            isScrolling = true;
            scrollStart = e.GetPosition(baseScrolledViewer);
            scrollStartOffcet = new Point(baseScrolledViewer.HorizontalOffset, baseScrolledViewer.VerticalOffset);
        }

        void baseScrolledViewer_PreviewMouseMove(object sender, MouseEventArgs e)
        {
            if (isScrolling == false) return;

            Point endPoint = e.GetPosition(baseScrolledViewer);

            baseScrolledViewer.ScrollToHorizontalOffset(scrollStart.X - endPoint.X + scrollStartOffcet.X);
            baseScrolledViewer.ScrollToVerticalOffset(scrollStart.Y - endPoint.Y + scrollStartOffcet.Y);
            e.Handled = true;
        }

        void baseScrolledViewer_PreviewMouseWheel(object sender, System.Windows.Input.MouseWheelEventArgs e)
        {
            //取键盘按键状态。
            //bool isShift = false;
            bool isCtrl = false;

            //KeyStates lShift = Keyboard.GetKeyStates(Key.LeftShift);
            //KeyStates rShift = Keyboard.GetKeyStates(Key.RightShift);
            KeyStates lCtrl = Keyboard.GetKeyStates(Key.LeftCtrl);
            KeyStates rCtrl = Keyboard.GetKeyStates(Key.RightCtrl);

            if ((lCtrl & KeyStates.Down) > 0 || (rCtrl & KeyStates.Down) > 0)
            {
                isCtrl = true;
            }

            ScrollViewer sviewer = sender as ScrollViewer;

            if (isCtrl)
            {
                //横向滚动
                sviewer.ScrollToHorizontalOffset(sviewer.HorizontalOffset - e.Delta);
            }
            else
            {
                //默认纵向滚动
                sviewer.ScrollToVerticalOffset(sviewer.VerticalOffset - e.Delta);
            }

            //禁用ScrolledViewer自带鼠标滚轮事件。
            e.Handled = true;
        }

        //private DragingAdorner mainAdorner;

        ///// <summary>
        ///// 备用的装饰器。
        ///// </summary>
        //public DragingAdorner MainAdorner
        //{
        //    get { return mainAdorner; }
        //    set { mainAdorner = value; }
        //}

        private AdornerDecorator mainDecorator;

        /// <summary>
        /// 主装饰器。
        /// </summary>
        public AdornerDecorator MainDecorator
        {
            get { return mainDecorator; }
            set { mainDecorator = value; }
        }

        private Canvas readonlyCanvas;

        private TextBlock textBlockModified;

        public MainWindow ParentWindow { get; set; }

        void baseScrolledViewer_PreviewKeyDown(object sender, System.Windows.Input.KeyEventArgs e)
        {
            // 禁用ScrolledViewer自带的快捷键。
            e.Handled = true;
        }

        void EditorOfExpression_SelectionExpressionChanged(object sender, SelectionExpressionChangedEventArgs e)
        {
            if (e.NewSelectionExpression == null) return;

            e.NewSelectionExpression.IsSelected = true;

            // 尝试在状态条上列出公式层结构。
            ListExpressionsTreeOnStatusBar(e.NewSelectionExpression);
            Globals.RefreshToolBarItemsWhenExpressionSelected(this.ParentWindow);

            Commands.Command.AutoLocation(e.NewSelectionExpression);
        }

        public void ListExpressionsTreeOnStatusBar(Expressions.Expression expression)
        {
            if (this != Globals.selectedEditor) return;

            ParentWindow.expressionsTreeListPanel.Children.Clear();

            if (expression == null) return;//这句放在此处最好。因为如果expression为null，还可以清空列表。

            Expressions.Expression ex = expression;
            while (ex != null)
            {
                // 按钮只支持选中。
                ExpressionLayerButton btn = new ExpressionLayerButton(ex);
                btn.PreviewKeyDown += new System.Windows.Input.KeyEventHandler(btn_PreviewKeyDown);

                ParentWindow.expressionsTreeListPanel.Children.Insert(0, btn);

                if (ex is Expressions.SubPanel)
                {
                    ex = (ex as Expressions.SubPanel).ParentExpression;
                }
                else
                {
                    ex = ex.ParentPanel;
                }
            }

            if (ParentWindow.expressionsTreeListPanel.Children.Count > 0)
            {
                int lastIndex = ParentWindow.expressionsTreeListPanel.Children.Count - 1;
                if (ParentWindow.expressionsTreeListPanel.Children[lastIndex] is ExpressionLayerButton)
                {
                    ExpressionLayerButton lastButton = ParentWindow.expressionsTreeListPanel.Children[lastIndex] as ExpressionLayerButton;
                    lastButton.IsLastLayer = true;
                }
            }

            ParentWindow.scvOfExLayersTree.ScrollToRightEnd();
        }

        void btn_PreviewKeyDown(object sender, System.Windows.Input.KeyEventArgs e)
        {
            if (e.Key == System.Windows.Input.Key.Enter)
            {
                e.Handled = true;
            }
        }

        void EditorOfExpression_SelectionExpressionChanging(object sender, SelectionExpressionChangingEventArgs e)
        {
            if (e.ExpressionIsChanging == null) return;

            e.ExpressionIsChanging.IsSelected = false;
        }

        void EditorOfExpression_EditorBeforeClosed(object sender, EditorBeforeClosedEventArgs e)
        {
            TabControl mainTabControl = this.Parent as TabControl;

            if (this.IsModified)
            {
                MessageBoxResult r = MessageBox.Show(
                    "《" + ((FileName == null || FileName.Length <= 0) ? fileNameHeader.Text : FileName)
                    + "》已被修改，要保存吗？", Globals.appName,
                    MessageBoxButton.YesNoCancel, MessageBoxImage.Warning);
                switch (r)
                {
                    case MessageBoxResult.Yes:
                        {
                            if (Commands.Command.SaveFile(this))
                            {
                                break;// 准备关闭。
                            }
                            else
                            {
                                e.DoClose = false;
                                return;// 取消。
                            }
                        }
                    case MessageBoxResult.No:
                        {
                            break;
                        }
                    default:// Cancel
                        {
                            e.DoClose = false;
                            return;
                        }
                }
            }

            // 关闭前先转移“当前编辑器”。

            int index = mainTabControl.Items.IndexOf(this);
            if (index >= 1)
            {
                mainTabControl.SelectedIndex = index - 1;
            }
            else if (index == 0)
            {
                if (mainTabControl.Items.Count > 1)
                {
                    mainTabControl.SelectedIndex = index + 1;
                }
                else
                {
                    mainTabControl.SelectedIndex = -1;
                }
            }

            mainTabControl.Items.Remove(this);

            if (mainTabControl.Items.Count <= 0)
            {
                Globals.selectedEditor = null;
                Globals.RefreshToolsWhenLastDocumentClosed(this.ParentWindow);
                this.ParentWindow.Title = Globals.appName;
                this.ParentWindow.EnableStatusControls(System.Windows.Visibility.Hidden);
            }
        }

        void imgClose_MouseLeftButtonDown(object sender, System.Windows.Input.MouseButtonEventArgs e)
        {
            Close();
        }

        public void Close()
        {
            EditorBeforeClosedEventArgs beforeCloseArgs = new EditorBeforeClosedEventArgs(this);
            OnEditorBeforeClosed(beforeCloseArgs);
        }

        protected void OnEditorBeforeClosed(EditorBeforeClosedEventArgs e)
        {
            if (EditorBeforeClosed != null)
            {
                EditorBeforeClosed(this, e);
            }

            if (e.DoClose)
            {
                if (this.Parent is TabControl)
                {
                    TabControl mainTabCtrl = this.Parent as TabControl;
                    mainTabCtrl.Items.Remove(this);
                    OnEditorClosed(new EditorClosedEventArgs(this));
                }
            }
        }

        protected void OnEditorClosed(EditorClosedEventArgs e)
        {
            if (EditorClosed != null)
            {
                EditorClosed(this, e);
            }
        }

        public event EventHandler<EditorBeforeClosedEventArgs> EditorBeforeClosed;

        public event EventHandler<EditorClosedEventArgs> EditorClosed;

        private BitmapImage normalImg;

        private BitmapImage activeImg;

        void imgClose_MouseLeave(object sender, System.Windows.Input.MouseEventArgs e)
        {
            Image img = sender as Image;
            imgClose.Source = normalImg;
        }

        void imgClose_MouseEnter(object sender, System.Windows.Input.MouseEventArgs e)
        {
            Image img = sender as Image;
            imgClose.Source = activeImg;
        }

        private TextBlock fileNameHeader;

        public TextBlock FileNameHeader
        {
            get { return fileNameHeader; }
            set { fileNameHeader = value; }
        }

        private string fileName;

        /// <summary>
        /// 全路径。
        /// </summary>
        public string FileName
        {
            get { return fileName; }
            set
            {
                fileName = value;
                fileNameHeader.Text = GetShortFilenameFromFullname(fileName);
            }
        }

        public static string GetShortFilenameFromFullname(string fullname)
        {
            if (fullname == null || fullname.Length <= 0) return string.Empty;

            int indexOfSprit = fullname.LastIndexOf('\\');
            if (indexOfSprit > 0 && indexOfSprit < fullname.Length - 1)
            {
                string shortname = fullname.Substring(indexOfSprit + 1);
                //if (shortname.EndsWith(".lpdoc") == false)
                //{
                //    shortname += ".lpdoc";
                //}
                return shortname;
            }
            else return string.Empty;
        }

        public string DocName
        {
            get { return fileNameHeader != null ? fileNameHeader.Text : ""; }
            set
            {
                if (fileNameHeader != null)
                {
                    fileNameHeader.Text = value;
                }
                else
                {
                    fileNameHeader = new TextBlock();
                    fileNameHeader.Text = value;
                }
            }
        }

        private Image imgClose;

        public Image ImgClose
        {
            get { return imgClose; }
            set { imgClose = value; }
        }

        private bool isModified = false;

        public bool IsModified
        {
            get { return isModified; }
            set
            {
                if (isModified != value)
                {
                    isModified = value;
                    if (isModified)
                    {
                        textBlockModified.Visibility = Visibility.Visible;
                    }
                    else
                    {
                        textBlockModified.Visibility = Visibility.Collapsed;
                    }
                }
            }
        }

        private bool isReadOnly = false;

        public bool IsReadOnly
        {
            get { return isReadOnly; }
            set
            {
                isReadOnly = value;
                if (isReadOnly)
                {
                    readonlyCanvas.Visibility = Visibility.Visible;
                    readonlyCanvas.ToolTip = fileNameHeader.ToolTip = "只读文档";
                }
                else
                {
                    readonlyCanvas.Visibility = Visibility.Collapsed;
                    readonlyCanvas.ToolTip = fileNameHeader.ToolTip = null;
                }
            }
        }

        public void SetExFontSizeWithoutEvents(double exfontsize)
        {
            exFontSize = exfontsize;
        }

        private double exFontSize = 12;

        /// <summary>
        /// 用于整体缩放的字号。当此一字号与文本块本身的字号冲突时，以文本块本身字号为“最小字号”。
        /// </summary>
        public double ExFontSize
        {
            get { return exFontSize; }
            set
            {
                exFontSize = value;

                // 刷新编辑器全局字体。
                TextElement.SetFontSize(this.rootPanel, value);

                this.rootPanel.XmlData.SetAttribute("ExFontSize", value.ToString());
                IsModified = true;
                OnPropertyChanged(this, new PropertyChangedEventArgs("ExFontSize"));
            }
        }

        private SubPanel rootPanel;

        public SubPanel RootPanel
        {
            get { return rootPanel; }
        }

        private XmlDocument xmlDocument;

        /// <summary>
        /// 此值被赋予某个Xml文档时，会根据文档内容生成相应各公式。
        /// 这是通过给根面板的“XmlData”属性赋值实现的。
        /// </summary>
        public XmlDocument XmlDocument
        {
            get { return xmlDocument; }
            set
            {
                xmlDocument = value;
                this.rootPanel.XmlData = xmlDocument.DocumentElement;
            }
        }

        private ScrollViewer baseScrolledViewer;

        /// <summary>
        /// 滚动面板。根面板是放在这个滚动面板中的。
        /// </summary>
        public ScrollViewer BaseScrolledViewer
        {
            get { return baseScrolledViewer; }
            set { baseScrolledViewer = value; }
        }

        private SHomeWorkshop.LunarPresentation.Expressions.Expression selectedExpression;

        public SHomeWorkshop.LunarPresentation.Expressions.Expression SelectedExpression
        {
            get { return selectedExpression; }
            set
            {
                //if (selectedExpression == value) return;
                //加这句会导致“嵌入‘行’”后无法刷新状态条层级列表。

                Globals.SwitchInputMethod(false);
                OnSelectionExpressionChanging(this,
                    new SelectionExpressionChangingEventArgs(selectedExpression));
                selectedExpression = value;
                OnSelectionExpressionChanged(this,
                    new SelectionExpressionChangedEventArgs(selectedExpression));
            }
        }

        public event EventHandler<SelectionExpressionChangingEventArgs> SelectionExpressionChanging;

        protected void OnSelectionExpressionChanging(Object sender,
            SelectionExpressionChangingEventArgs e)
        {
            if (SelectionExpressionChanging != null)
            {
                SelectionExpressionChanging(sender, e);
            }
        }

        public event EventHandler<SelectionExpressionChangedEventArgs> SelectionExpressionChanged;

        protected void OnSelectionExpressionChanged(Object sender,
            SelectionExpressionChangedEventArgs e)
        {
            if (SelectionExpressionChanged != null)
            {
                SelectionExpressionChanged(sender, e);
            }
        }

        protected void OnPropertyChanged(object sender,
            PropertyChangedEventArgs e)
        {
            if (PropertyChanged != null)
            {
                PropertyChanged(sender, e);
            }
        }

        #region INotifyPropertyChanged Members

        public event PropertyChangedEventHandler PropertyChanged;

        #endregion

        private ModifingsList modifingsList;

        public ModifingsList ModifingsList
        {
            get { return modifingsList; }
        }

        /// <summary>
        /// 这个方法仅仅只是封装了ModifingItem的Do()方法——便于调用而已。
        /// 没有添加任何其它代码。
        /// </summary>
        /// <param name="modifingItem"></param>
        public void Do(ModifingItem modifingItem)
        {
            if (modifingsList != null)
            {
                modifingsList.Do(modifingItem);
            }
        }

        /// <summary>
        /// 这个方法仅仅只是封装了ModifingItem的UnDo()方法——便于调用而已。
        /// 没有添加任何其它代码。
        /// </summary>
        public void Undo()
        {
            if (modifingsList != null)
            {
                modifingsList.Undo();
            }
        }

        /// <summary>
        /// 这个方法仅仅只是封装了ModifingItem的ReDo()方法——便于调用而已。
        /// 没有添加任何其它代码。
        /// </summary>
        public void Redo()
        {
            if (modifingsList != null)
            {
                modifingsList.Redo();
            }
        }

        /// <summary>
        /// 根据内部编号来递归寻找公式。
        /// </summary>
        /// <param name="expression">通常应传入根面板。</param>
        /// <param name="exID">内部编号，是一个Guid字符串。同一编辑器在运行时，任意两个公式的内部编号是不重复的。</param>
        /// <returns></returns>
        public Expressions.Expression GetExpressionByExID(Expressions.Expression expression, string exID)
        {
            if (expression == null) return null;

            if (expression.ExID == exID) return expression;

            if (expression is SubPanel)
            {
                SubPanel subPanel = expression as Expressions.SubPanel;
                for (int i = 0; i < subPanel.BasePanel.Children.Count; i++)
                {
                    Expressions.Expression ex = subPanel.BasePanel.Children[i] as Expressions.Expression;
                    if (ex.ExID == exID) return ex;
                    else
                    {
                        Expressions.Expression subEx = GetExpressionByExID(ex, exID);
                        if (subEx != null) return subEx;
                    }
                }
            }
            else
            {
                //普通公式，且本身并非目标。
                if (expression.SubPanels != null && expression.SubPanels.Count > 0)
                {
                    foreach (SubPanel sPanel in expression.SubPanels)
                    {
                        if (sPanel.ExID == exID) { return sPanel; }
                        else
                        {
                            Expressions.Expression subEx = GetExpressionByExID(sPanel, exID);
                            if (subEx != null) return subEx;
                        }
                    }
                }
            }

            return null;
        }



        #region 公式的选取框色彩。
        private Brush exSelectionAdornerBrush = Brushes.GreenYellow;

        public Brush ExSelectionAdornerBrush
        {
            get { return exSelectionAdornerBrush; }
            set
            {
                string oldBrushName = ColorPicker.GetBrushName(exSelectionAdornerBrush);
                string newBrushName = ColorPicker.GetBrushName(value);

                exSelectionAdornerBrush = value;

                if (this.rootPanel != null)
                {
                    this.rootPanel.XmlData.SetAttribute("ExSelectionAdornerBrush",
                        newBrushName);
                }

                RefreshAllExSelectionAdornerBrush(this.rootPanel);
            }
        }

        private void RefreshAllExSelectionAdornerBrush(Expressions.Expression ex)
        {
            if (ex == null) return;

            ex.RefreshSelectAdorner();

            if (ex is SubPanel)
            {
                SubPanel spanel = ex as SubPanel;
                foreach (UIElement ue in spanel.BasePanel.Children)
                {
                    Expressions.Expression subEx = ue as Expressions.Expression;

                    if (subEx != null)
                    {
                        RefreshAllExSelectionAdornerBrush(subEx);
                    }
                }
            }
            else
            {
                if (ex.SubPanels == null) return;

                foreach (SubPanel subPanel in ex.SubPanels)
                {
                    RefreshAllExSelectionAdornerBrush(subPanel);
                }
            }
        }

        private Pen exSelectionAdornerPen = null;

        public Pen ExSelectionAdornerPen
        {
            get
            {
                if (exSelectionAdornerBrush == null) return null;

                if (exSelectionAdornerPen == null)
                {
                    return new Pen(exSelectionAdornerBrush, 1);
                }

                if (exSelectionAdornerPen.Brush ==
                    exSelectionAdornerBrush)
                {
                    return exSelectionAdornerPen;
                }
                else
                {
                    return new Pen(exSelectionAdornerBrush, 1);
                }
            }
        }

        private Brush subPanelSelectionAdornerBrush = Brushes.HotPink;

        public Brush SubPanelSelectionAdornerBrush
        {
            get { return subPanelSelectionAdornerBrush; }
            set
            {
                string oldBrushName = ColorPicker.GetBrushName(subPanelSelectionAdornerBrush);
                string newBrushName = ColorPicker.GetBrushName(value);

                subPanelSelectionAdornerBrush = value;

                if (this.rootPanel != null)
                {
                    this.rootPanel.XmlData.SetAttribute("SubPanelSelectionAdornerBrush",
                        newBrushName);
                }

                RefreshAllExSelectionAdornerBrush(this.rootPanel);
            }
        }

        private Pen subPanelSelectionAdornerPen = null;

        public Pen SubPanelSelectionAdornerPen
        {
            get
            {
                if (subPanelSelectionAdornerBrush == null) return null;

                if (subPanelSelectionAdornerPen == null)
                {
                    return new Pen(subPanelSelectionAdornerBrush, 1);
                }

                if (subPanelSelectionAdornerPen.Brush ==
                    subPanelSelectionAdornerBrush)
                {
                    return subPanelSelectionAdornerPen;
                }
                else
                {
                    return new Pen(subPanelSelectionAdornerBrush, 1);
                }
            }
        }
        #endregion

        private bool isOpened = false;

        //此属性用于在打开文档的过程中阻止可能发生的不当操作。
        public bool IsOpened
        {
            get { return isOpened; }
            set { isOpened = value; }
        }

        private bool autoWrap = true;

        /// <summary>
        /// 决定文本块是否自动折行。默认值为：true。
        /// </summary>
        public bool AutoWrap
        {
            get { return autoWrap; }
            set
            {
                autoWrap = value;
                this.xmlDocument.DocumentElement.SetAttribute("AutoWrap", autoWrap.ToString());
                OnPropertyChanged(this, new PropertyChangedEventArgs("AutoWrap"));
            }
        }
    }

    public class EditorClosedEventArgs : EventArgs
    {
        public EditorClosedEventArgs(Editor editor)
        {
            this.editor = editor;
        }

        private Editor editor;

        public Editor Editor
        {
            get { return editor; }
            set { editor = value; }
        }
    }

    public class EditorBeforeClosedEventArgs : EventArgs
    {
        public EditorBeforeClosedEventArgs(Editor editor)
        {
            this.editor = editor;
        }

        private bool doClose = true;

        public bool DoClose
        {
            get { return doClose; }
            set { doClose = value; }
        }

        private Editor editor;

        public Editor Editor
        {
            get { return editor; }
            set { editor = value; }
        }
    }

    public class SelectionExpressionChangingEventArgs : EventArgs
    {
        public SelectionExpressionChangingEventArgs(
            SHomeWorkshop.LunarPresentation.Expressions.Expression expression)
        {
            this.expressionIsChanging = expression;
        }

        private SHomeWorkshop.LunarPresentation.Expressions.Expression expressionIsChanging;

        public SHomeWorkshop.LunarPresentation.Expressions.Expression ExpressionIsChanging
        {
            get { return expressionIsChanging; }
            set { expressionIsChanging = value; }
        }
    }

    public class SelectionExpressionChangedEventArgs : EventArgs
    {
        public SelectionExpressionChangedEventArgs(
            SHomeWorkshop.LunarPresentation.Expressions.Expression expression)
        {
            this.newSelectionExpression = expression;
        }

        private SHomeWorkshop.LunarPresentation.Expressions.Expression newSelectionExpression;

        public SHomeWorkshop.LunarPresentation.Expressions.Expression NewSelectionExpression
        {
            get { return newSelectionExpression; }
            set { newSelectionExpression = value; }
        }
    }
}
